using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Profile;
using System.Configuration;
using System.Data.SqlClient;
using System.Diagnostics;

namespace Axe.Web.Security.Membership.Implementation
{
    
    public sealed class SqlSiteProfileProvider : SiteProfileProvider
    {
        String m_ConnectionString;

        public SqlSiteProfileProvider(String connectionString)
        {
            m_ConnectionString = connectionString;
        }

        public override int DeleteInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public override int DeleteProfiles(string[] usernames)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public override int DeleteProfiles(ProfileInfoCollection profiles)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public override ProfileInfoCollection FindInactiveProfilesByUserName(ProfileAuthenticationOption authenticationOption, string usernameToMatch, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public override ProfileInfoCollection FindProfilesByUserName(ProfileAuthenticationOption authenticationOption, string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public override ProfileInfoCollection GetAllInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate, int pageIndex, int pageSize, out int totalRecords)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public override ProfileInfoCollection GetAllProfiles(ProfileAuthenticationOption authenticationOption, int pageIndex, int pageSize, out int totalRecords)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public override int GetNumberOfInactiveProfiles(ProfileAuthenticationOption authenticationOption, DateTime userInactiveSinceDate)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #region public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection)
        public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection collection)
        {
            string username = (string)context["UserName"];
            bool isAuthenticated = (bool)context["IsAuthenticated"];

            SettingsPropertyValueCollection svc = new SettingsPropertyValueCollection();

            if (!isAuthenticated)
                return svc;

            foreach (SettingsProperty prop in collection)
            {
                SettingsPropertyValue pv = new SettingsPropertyValue(prop);

                object pValue;
                if (GetProperty(username, prop.Name, out pValue))
                    pv.PropertyValue = pValue;
                else
                    pv.PropertyValue = pv.Property.DefaultValue;

                svc.Add(pv);
            } 
        #endregion

            //UpdateActivityDates(username, isAuthenticated, true);

            return svc;
        }

        #region public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection collection)
        public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection collection)
        {
            string username = (string)context["UserName"];
            bool isAuthenticated = (bool)context["IsAuthenticated"];

            if (!isAuthenticated)
                return;

            foreach (SettingsPropertyValue pv in collection)
            {
                SetProperty(username, pv.Name, pv.PropertyValue);
            }

            //UpdateActivityDates(username, isAuthenticated, false);            

        } 
        #endregion
        /*
        private void UpdateActivityDates(string username, bool isAuthenticated, bool p)
        {
            throw new Exception("The method or operation is not implemented.");
        }
        */
        #region private bool SetProperty(string userName, string propertyName, string propertyValue)
        private bool SetProperty(string userName, string propertyName, object propertyValue)
        {
            SqlConnection conn = CreateConnection();
            SqlCommand cmd = conn.CreateCommand();

            cmd.CommandText = "SELECT COUNT(*) FROM [ProfileData] WHERE (UserName = @UserName) AND (PropertyName = @PropertyName)";
            cmd.Parameters.AddWithValue("@UserName", userName);
            cmd.Parameters.AddWithValue("@PropertyName", propertyName);

            try
            {
                conn.Open();
                bool hasRows = (int)cmd.ExecuteScalar() > 0;
                cmd.Parameters.AddWithValue("@PropertyValue", propertyValue);
                if (hasRows)
                {
                    cmd.CommandText = "UPDATE [ProfileData] SET PropertyValue=@PropertyValue WHERE (UserName = @UserName) AND (PropertyName = @PropertyName)";
                }
                else
                {
                    cmd.CommandText = "INSERT INTO [ProfileData] (UserName,PropertyName,PropertyValue) VALUES (@UserName,@PropertyName,@PropertyValue)";
                }
                return cmd.ExecuteNonQuery() > 0;
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.Message);
                return false;
            }
            finally
            {
                conn.Close();
            }
        } 
        #endregion

        #region private bool GetProperty(string userName, string propertyName, out object propertyValue)
        private bool GetProperty(string userName, string propertyName, out object propertyValue)
        {
            SqlConnection conn = CreateConnection();
            SqlCommand cmd = conn.CreateCommand();

            cmd.CommandText = "SELECT PropertyValue FROM [ProfileData] WHERE (UserName = @UserName) AND (PropertyName = @PropertyName)";
            cmd.Parameters.AddWithValue("@UserName", userName);
            cmd.Parameters.AddWithValue("@PropertyName", propertyName);

            try
            {
                conn.Open();
                object o = cmd.ExecuteScalar();
                if (o == null || o is DBNull)
                {
                    propertyValue = null;
                    return false;
                }

                propertyValue = o;
                return true;
            }
            catch (Exception e)
            {
                Debug.WriteLine(e.Message);
                propertyValue = null;
                return false;
            }
            finally
            {
                conn.Close();
            }
        } 
        #endregion

        private SqlConnection CreateConnection()
        {
            return new SqlConnection(m_ConnectionString);
        }
    }
    
}
